#!/usr/bin/env bash
# Example implementation of progressbar for ffmpeg written in pure bash.
#
# Works only using bash, no third party special dependencies needed. Progress
# percentage is shown in decimal places (e.g. 45.12%, which is done with awk,
# without anything like bc), so very useful for large files and extremely
# portable.
#
# License: CC0

# Usage:
# Just pass a video file to this script. e.g.
#   $ /path/to/ffmpeg-progressbar.sh somefile.mp4

# Input file name
source="$1"

# Get total frames in the source video
# Ref: https://stackoverflow.com/a/28376817
total_frames=$(ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 "$source")


# Use any ffmpeg command here
# But be sure to keep "-progress /dev/stdout -nostats" intact
ffmpeg -progress /dev/stdout -nostats -i "$source" "${source}.ogv" | while IFS='=' read -r key value; do
	# This is run for each line of the progress output. It may or may not have
	# frame data. 'frame' data is the number of frame that are done processing.
	# A line like 'frame=1234' is passed and IFS='=' devides the key and value.
	# So $key has 'frame' and $value has '1234'.
	# When "frame" data is passed to us, we update the progressbar.
	if [ "$key" = 'frame' ]; then
		current_frame="$value"
		# Calculations
		# A clever little trick to calculate float numbers with bash
		# Ref: https://stackoverflow.com/a/22406193
		progress_percentage=$(awk "BEGIN {printf \"%.2f\",${current_frame}/${total_frames}*100}")
		progress_int=$(( ${progress_percentage%.*} / 2 ))
		# Progress bar
		echo -n '['
		for ((i = 0 ; i <= $progress_int; i++)); do echo -n '#'; done
		for ((j = i ; j <= 50 ; j++)); do echo -n '-'; done
		echo -n '] '
		# Progress text
		echo -n "total frames: ${total_frames} done: ${current_frame} - ${progress_percentage}%" $'\r'
	fi
done
